#include <iostream>
#include <string>
#include <memory>
#include <functional>
#include "udpserver.hpp"
#include "InetAddr.hpp"
#include "Route.hpp"
#include "ThreadPool.hpp"

using namespace ThreadPoolModule;

using task_t = std::function<void()>;
int main(int argc, char *argv[])
{
    if(argc != 2){
        std::cerr << "Usage-> " << argv[0] << "[port]" << std::endl;
    }
    u_int16_t port = std::stoi(argv[1]);


    //std::unique_ptr<UDPsocket> server = std::make_unique<UDPsocket>(port, handle);
    //std::unique_ptr<UDPsocket> server = std::make_unique<UDPsocket>(port, [&](const std::string &word, InetAddr &client)->std::string{
    //    return dict.Translate(word, client);
    //} );

    // 1.创建消息路由
    route r; 

    // 2.我们现在的服务器是单线程模式，只有一个线程，收到消息后，就进行路由
    // 这里我们引入线程池，将客户端发送的消息当作一个任务
    // 服务端收到之后，派发给线程池中的空闲线程去执行
    auto tp = ThreadPool<task_t>::Getinstance(); // 获取单例线程池

    // 3.网络服务，将收到的消息放入线程池的任务队列中，让后端线程去路由消息
    std::unique_ptr<UDPsocket> server = std::make_unique<UDPsocket>(port, [&r, &tp](int sockfd, const std::string message, InetAddr &client){
        // 原本网络服务端，使用该方法就是直接去路由消息
        // 这里引入线程池，所以服务端主线程的任务就变成了将路由的消息作为任务插入到线程池的任务队列中
        // 让线程池去执行
        // 3.1定制任务
        task_t t = std::bind(&route::messag_routing, &r, sockfd, message, client); 
        tp->emplace(t);
    });

    //std::unique_ptr<UDPsocket> server = std::make_unique<UDPsocket>(port, [&r](int sockfd, const std::string &message, InetAddr &client){
    //    r.messag_routing(sockfd, message, client);
    //} );
    server->Init();
    server->Start();
    
    return 0;
}